/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import 'package:audio_session/audio_session.dart';
import 'package:flutter/foundation.dart';
import 'package:just_audio_ohos/just_audio_ohos.dart';
import 'package:rxdart/rxdart.dart';

class AudioPlayerManager {
  static final AudioPlayerManager _instance = AudioPlayerManager._internal();
  final ValueNotifier<Map> currentData = ValueNotifier<Map>({});
  List<Map> _dataList = [];
  int _currentIndex = -1;

  factory AudioPlayerManager() {
    return _instance;
  }

  AudioPlayerManager._internal();

  final AudioPlayer audioPlayer = AudioPlayer();

  init(List<Map> dataList,int currentIndex){
    _dataList = dataList;
    _currentIndex = currentIndex;
    if(currentIndex >= 0 && currentIndex < _dataList.length){
      currentData.value = _dataList[currentIndex];
    }
    _initAudio();
  }

  void _initAudio() async {
    final session = await AudioSession.instance;
    await session.configure(const AudioSessionConfiguration.speech());
    audioPlayer.playbackEventStream.listen((event) {},
        onError: (Object e, StackTrace stackTrace) {
          if (kDebugMode) {
            print('A stream error occurred: $e');
          }
        });
    _updatePlayerAsset();
  }

  _updatePlayerAsset() async {
    try {
      await audioPlayer.setAsset(currentData.value["url"]);
      audioPlayer.seek(Duration.zero);
    } on PlayerException catch (e) {
      if (kDebugMode) {
        print("Error loading audio source: $e");
      }
    }
  }

  setCurrentIndex(int currentIndex){
    if(currentIndex >= 0 && currentIndex < _dataList.length){
      _currentIndex = currentIndex;
      currentData.value = _dataList[currentIndex];
      _updatePlayerAsset();
    }
  }

  void playPrevious() {
    if (_currentIndex > 0) {
      setCurrentIndex(--_currentIndex);
    }
  }

  void playNext() {
    if (_currentIndex < _dataList.length - 1) {
      setCurrentIndex(++_currentIndex);
    }
  }

  Future<void> play() async {
    await audioPlayer.play();
  }

  Future<void> pause() async {
    await audioPlayer.pause();
  }

  Future<void> stop() async {
    await audioPlayer.stop();
  }

  Future<void> seek(Duration duration) async {
    await audioPlayer.seek(duration);
  }

  Future<void> dispose() async {
    await audioPlayer.dispose();
  }

  Stream<PositionData> get positionDataStream =>
      Rx.combineLatest3<Duration, Duration, Duration?, PositionData>(
          audioPlayer.positionStream,
          audioPlayer.bufferedPositionStream,
          audioPlayer.durationStream,
              (position, bufferedPosition, duration) => PositionData(
              position, bufferedPosition, duration ?? Duration.zero));
}

class PositionData {
  final Duration position;
  final Duration bufferedPosition;
  final Duration duration;

  PositionData(this.position, this.bufferedPosition, this.duration);
}